# -*- coding: utf-8 -*-
###############################################################################
# file    : views_bug.py
# author  : wangyubin
# date    : Thu Apr 17 13:23:41 2014
#
# brief   : views for bug 管理
# history : init
#         : 2014-05-01 -->
#         : 追加bug的comment
#         : 追加bug的履历
###############################################################################

# uliweb lib
from uliweb import expose, functions
from uliweb.mail import Mail
# python lib
import os
import datetime
# CM-box lib
from db_app.model_define import *
from comm_app.my_log import App_Log
from comm_app import utils

@expose('/bug')
class views_bug(object):
    """ bug 管理
    """

    def __save_bug_attachments(self, bug, attachment_ids):
        """ 保存bug的附件
        """
        # bug 相关附件
        for attachment_id in attachment_ids:
            ba = T_BUG_ATTACHMENT.get(int(attachment_id))
            ba.bug = bug
            # 附件移动到 对应bug的文件夹下
            new_filepath = os.path.join(settings.PATH.ATTACHMENT, str(bug.id), ba.name)
            utils.copy_file(ba.path, new_filepath)
            ba.path = new_filepath
            ba.save()

        # 删除临时附件
        tmp_folder = "tmp-" + request.user.name
        utils.remove_file_or_dir(os.path.join(settings.PATH.ATTACHMENT, tmp_folder))


    def __save_bug_history(self, bug):
        """ 保存bug履历
        """
        bug_history = T_BUG_HISTORY()
        bug_history.title = bug.title
        bug_history.desc = bug.desc
        bug_history.bug_importance = bug.bug_importance
        bug_history.bug_state = bug.bug_state
        bug_history.project = bug.project
        bug_history.update_time = bug.update_time
        bug_history.create_time = bug.create_time
        bug_history.assign_from_user = bug.assign_from_user
        bug_history.assign_to_user = bug.assign_to_user
        bug_history.create_user = bug.create_user
        bug_history.bug = bug
        bug_history.save()


    def __mail_content(self, bug):
        """ 生成bug通知邮件的内容
        """
        content = u"此BUG由 「%s」 分配给 「%s」" % \
                  (bug.assign_from_user.real_name, bug.assign_to_user.real_name)
        content += u"\n\n******************** BUG 状态 ********************"
        content += u"\nBUG 所属工程：「%s」" %  bug.project.name
        content += u"\nBUG 状态    ：「%s」" %  bug.bug_state.name
        content += u"\nBUG 重要性  ：「%s」" %  bug.bug_importance.name
        content += "\n**************************************************"
        
        content += u"\n\n******************** BUG 描述 ********************"
        content += "\n" + bug.desc
        content += "\n**************************************************"

        comments = bug.bug_comments.order_by(T_BUG_COMMENT.c.update_time.desc())
        if comments.count() > 0:
            content += u"\n\n******************** BUG 备注 ********************"
            for c in comments:
                content += "\n" + utils.datetime2str(c.create_time, utils.DATE_FORMAT4)
                content += "\t" + c.create_user.real_name + u" 追加了备注："
                content += "\t" + c.comment
            content += "\n**************************************************"

        histories = bug.bug_histories.order_by(T_BUG_HISTORY.c.create_time)
        if histories.count() > 0:
            content += u"\n\n******************** BUG 修改履历 ********************"
            for h in histories:
                content += "\n" + utils.datetime2str(h.update_time, utils.DATE_FORMAT4)
                content += "\t" + h.assign_from_user.real_name + "  -->  " + h.assign_to_user.real_name
            content += "\n**********************************************************"

        return content



    @expose('list')
    def list(self):
        """ 显示所有相关的bug
        """
        user = request.user
        if user.projects.count() == 0:
            return '<h1>当前用户还没有分配项目, 请联系管理员!!! <a href="/auth/logout">由此退出</a></h1>'

        p_default_id = 1
        if request.session[settings.SESSION.SESSION_ID].get("current-project", False):
            p_default_id = request.session[settings.SESSION.SESSION_ID]["current-project"]

        return {
            "p_default": user.projects.get(p_default_id),
            "projects": user.projects.filter(T_PROJECT.c.id != p_default_id),
        }


    @expose('edit/<int:proj_id>/<int:bug_id>')
    def edit(self, proj_id, bug_id):
        """ 显示bug详细信息(用于新建或者修改)
            bug_id == 0 时, 新建bug
        """
        user = request.user
        p_default =  user.projects.get(proj_id)
        projects = user.projects.filter(T_PROJECT.c.id != proj_id)

        if bug_id == 0:         # 新建bug
            assign_users = T_USER.filter(T_USER.c.name != 'admin')\
                                 .filter(T_USER.c.name != user.name)
            return {
                "breadnav": u"新建 BUG",
                "bug_id": 0,
                "bug_title": "",
                "bug_desc": "",
                "bi_default": T_BUG_IMPORTANCE.get(1),
                "bug_importances": T_BUG_IMPORTANCE.filter(T_BUG_IMPORTANCE.c.id > 1),
                "bs_default": T_BUG_STATE.get(1),
                "bug_states": T_BUG_STATE.filter(T_BUG_STATE.c.id > 1),
                "assign_default": user,
                "bug_assign_to": assign_users,
                "bug_attachments": [],
                "p_default": p_default,
                "projects": projects,
            }
        else:                   # 编辑bug
            bug = T_BUG.get(bug_id)
            assign_users = T_USER.filter(T_USER.c.name != 'admin')\
                                 .filter(T_USER.c.name != bug.assign_to_user.name)
            return {
                "breadnav": u"编辑 BUG",
                "bug_id": bug_id,
                "bug_title": bug.title,
                "bug_desc": bug.desc,
                "bi_default": bug.bug_importance,
                "bug_importances": T_BUG_IMPORTANCE.filter(T_BUG_IMPORTANCE.c.id != bug.bug_importance.id),
                "bs_default": bug.bug_state,
                "bug_states": T_BUG_STATE.filter(T_BUG_STATE.c.id != bug.bug_state.id),
                "assign_default": bug.assign_to_user,
                "bug_assign_to": assign_users,
                "bug_attachments": bug.bug_attachments,
                "p_default": p_default,
                "projects": projects,
                "comments": bug.bug_comments,
                "bug_histories": bug.bug_histories.order_by(T_BUG_HISTORY.c.update_time),
            }


    @expose('upload-attachment')
    def upload_attachment(self):
        """ 上传bug的附件
        上传的文件首先放在临时文件夹中
        保存bug 之后, 再和bug关联起来
        """
        user = request.user
        tmp_folder = "tmp-" + user.name

        file = request.files.get("file-bug-attachment")
        filepath = os.path.join(settings.PATH.ATTACHMENT, tmp_folder, file.filename)

        utils.upload_file(filepath, file)
        ba = T_BUG_ATTACHMENT()
        ba.name = file.filename
        ba.path = filepath
        ba.save()

        return json({
            "result": "OK",
            "message": "",
            "ba_name": ba.name,
            "ba_id": ba.id,
        })


    @expose('download-attachment/<int:ba_id>')
    def download_attachment(self, ba_id):
        """ 下载指定的附件
        """
        App_Log.logger.debug(u'bug attachment id: ' + str(ba_id))

        ba = T_BUG_ATTACHMENT.get(ba_id)
        print ba.path
        return utils.download_file(request.environ, ba.path)


    @expose('change-project')
    def change_project(self):
        """ 切换项目
        """
        proj_id = request.POST.get("proj_id")
        App_Log.logger.debug(u'proj_id: ' + proj_id)

        proj = T_PROJECT.get(int(proj_id))
        request.session[settings.SESSION.SESSION_ID]["current-project"] = proj.id
        return json({
            "result": "OK",
            "message": settings.MESSAGE.BUG_MSG_02 % proj.name,
        })


    @expose('save')
    def save(self):
        """ 保存 BUG
        """
        bug_id         = request.POST.get("bug_id")
        proj_id        = request.POST.get("proj_id")
        bug_title      = request.POST.get("bug_title")
        bug_desc       = request.POST.get("bug_desc")
        bi_code        = request.POST.get("bi_code")
        bs_code        = request.POST.get("bs_code")
        assign_to_id   = request.POST.get("assign_to_id")
        attachment_ids = request.POST.getlist("attachment_ids[]")
        comment        = request.POST.get("comment")

        App_Log.logger.debug(u'bug_id: ' + bug_id)
        App_Log.logger.debug(u'proj_id: ' + proj_id)
        App_Log.logger.debug(u'bug_title: ' + bug_title)
        App_Log.logger.debug(u'bug_desc: ' + bug_desc)
        App_Log.logger.debug(u'bi_code: ' + bi_code)
        App_Log.logger.debug(u'bs_code: ' + bs_code)
        App_Log.logger.debug(u'assign_to_id: ' + assign_to_id)
        App_Log.logger.debug(u'attachment_ids: ' + repr(attachment_ids))
        App_Log.logger.debug(u'comment:' + repr(comment))

        user = request.user
        bug = T_BUG()
        if int(bug_id) == 0:    # 新建
            bug.create_user = user
        else:                   # 编辑
            bug = T_BUG.get(int(bug_id))

        bug.project = T_PROJECT.get(int(proj_id))
        bug.title = bug_title   # bug 标题
        bug.desc = bug_desc     # bug 描述
        bug.assign_from_user = user # bug 指派者
        bi = T_BUG_IMPORTANCE.filter(T_BUG_IMPORTANCE.c.code == int(bi_code)).one()
        bug.bug_importance = bi # bug重要性
        bs = T_BUG_STATE.filter(T_BUG_STATE.c.code == int(bs_code)).one()
        bug.bug_state = bs      # bug状态
        assign_to_user = T_USER.get(int(assign_to_id))
        bug.assign_to_user = assign_to_user # bug的对应者
        bug.save()

        # 保存 bug 附件
        self.__save_bug_attachments(bug, attachment_ids)

        # 保存 bug 备注
        if comment and len(comment.strip()) > 0:
            bug_comment = T_BUG_COMMENT()
            bug_comment.comment = comment
            bug_comment.bug = bug
            bug_comment.create_user = user
            bug_comment.update_user = user
            bug_comment.save()

        # 追加bug 履历
        self.__save_bug_history(bug)

        # 发送邮件通知bug更新
        App_Log.logger.debug(u'开始发送邮件... ...')
        Mail().send_mail(settings.MAIL.USER, assign_to_user.email, "[BUG: " + bs.name + "] " + bug_title, \
                         self.__mail_content(bug))
        App_Log.logger.debug(u'邮件发送完成！')

        return json({
            "result": "OK",
            "message": "",
        })


    @expose('delete')
    def delete(self):
        """ 删除bug
        """
        bug_id = request.POST.get("bug_id")
        App_Log.logger.debug(u'bug_id: ' + bug_id)

        bug = T_BUG.get(int(bug_id))
        if bug.create_user.id != request.user.id: # 不是bug的创建者不能删除bug
            return json({
                "result": "NG",
                "message": settings.MESSAGE.BUG_MSG_01,
            })

        # 删除 BUG 的附件
        if bug.bug_attachments:
            bug.bug_attachments.remove()

        utils.remove_file_or_dir(os.path.join(settings.PATH.ATTACHMENT, str(bug.id)))
        bug.delete()

        return json({
            "result": "OK",
            "message": "",
        })


    @expose('search')
    def search_bug(self):
        """ 根据ID检索BUG
        """
        bug_id = request.POST.get("bug_id")
        App_Log.logger.debug(u'bug_id: ' + bug_id)

        bug = T_BUG.get(int(bug_id))

        if not bug:
            return json({
                "result": "NG",
                "message": settings.MESSAGE.BUG_MSG_03,
            })

        return json({
            "result": "OK",
            "message": "",
            "project_id": bug.project.id,
        })


    @expose('created-bugs')
    def get_created_bugs(self):
        """ 我创建的bug (当前项目下)
        """

        proj_id = request.POST.get("proj_id")
        user = request.user
        dt = []
        bug_state = T_BUG_STATE.filter(T_BUG_STATE.c.code == 8).one() # 不包含 已确认 的bug
        created_bugs = T_BUG.filter(T_BUG.c.create_user == T_USER.c.id) \
                            .filter(T_USER.c.id == user.id) \
                            .filter(T_BUG.c.project == T_PROJECT.c.id)\
                            .filter(T_PROJECT.c.id == int(proj_id)) \
                            .filter(T_BUG.c.bug_state != bug_state.id) \
                            .order_by(T_BUG.c.update_time.desc())
        for bug in created_bugs:
            dr = [
                '<a href="/bug/edit/'+proj_id+'/'+str(bug.id)+'">' + str(bug.id) + '</a>',
                utils.fix_str_len(bug.title),
                utils.datetime2str(bug.update_time, utils.DATE_FORMAT5),
                bug.bug_state.name,
            ]
            dt.append(dr)

        return json({
            "aaData": dt,
        })


    @expose('confirmed-bugs')
    def get_confirmed_bugs(self):
        """ 我已经确认的bug
        assign_to_user == 我
        bug_state == 8 (已确认)
        """
        proj_id = request.POST.get("proj_id")
        user = request.user
        dt = []
        created_bugs = T_BUG.filter(T_BUG.c.assign_to_user == T_USER.c.id) \
                            .filter(T_USER.c.id == user.id) \
                            .filter(T_BUG.c.project == T_PROJECT.c.id)\
                            .filter(T_PROJECT.c.id == int(proj_id)) \
                            .filter(T_BUG.c.bug_state == T_BUG_STATE.c.id) \
                            .filter(T_BUG_STATE.c.code == 8) \
                            .order_by(T_BUG.c.update_time.desc())
        for bug in created_bugs:
            dr = [
                '<a href="/bug/edit/'+proj_id+'/'+str(bug.id)+'">' + str(bug.id) + '</a>',
                utils.fix_str_len(bug.title),
                utils.datetime2str(bug.update_time, utils.DATE_FORMAT5),
                bug.bug_state.name,
            ]
            dt.append(dr)

        return json({
            "aaData": dt,
        })


    @expose('assigning-bugs')
    def get_assigning_bugs(self):
        """ 等待我对应的bug
        assign_to_user == 我
        bug_state == 2 (已分派)
        """
        proj_id = request.POST.get("proj_id")
        user = request.user
        dt = []
        created_bugs = T_BUG.filter(T_BUG.c.assign_to_user == T_USER.c.id) \
                            .filter(T_USER.c.id == user.id) \
                            .filter(T_BUG.c.project == T_PROJECT.c.id)\
                            .filter(T_PROJECT.c.id == int(proj_id)) \
                            .filter(T_BUG.c.bug_state == T_BUG_STATE.c.id) \
                            .filter(T_BUG_STATE.c.code == 2) \
                            .order_by(T_BUG.c.update_time.desc())
        for bug in created_bugs:
            dr = [
                '<a href="/bug/edit/'+proj_id+'/'+str(bug.id)+'">' + str(bug.id) + '</a>',
                utils.fix_str_len(bug.title),
                utils.datetime2str(bug.update_time, utils.DATE_FORMAT5),
                bug.create_user.real_name,
            ]
            dt.append(dr)

        return json({
            "aaData": dt,
        })


    @expose('confirming-bugs')
    def get_confirming_bugs(self):
        """ 等待我确认的bug
        assign_to_user == 我
        bug_state == 4 (已对应)
        """
        proj_id = request.POST.get("proj_id")
        user = request.user
        dt = []
        created_bugs = T_BUG.filter(T_BUG.c.assign_to_user == T_USER.c.id) \
                            .filter(T_USER.c.id == user.id) \
                            .filter(T_BUG.c.project == T_PROJECT.c.id)\
                            .filter(T_PROJECT.c.id == int(proj_id)) \
                            .filter(T_BUG.c.bug_state == T_BUG_STATE.c.id) \
                            .filter(T_BUG_STATE.c.code == 4) \
                            .order_by(T_BUG.c.update_time.desc())
        for bug in created_bugs:
            dr = [
                '<a href="/bug/edit/'+proj_id+'/'+str(bug.id)+'">' + str(bug.id) + '</a>',
                utils.fix_str_len(bug.title),
                utils.datetime2str(bug.update_time, utils.DATE_FORMAT5),
                bug.assign_from_user.real_name,
            ]
            dt.append(dr)

        return json({
            "aaData": dt,
        })


